//  [2/19/2009 Gavan Acton]
#pragma once

#include <map>
#include <string>
#include "BasicObject.h"
#include "Functions.h"

namespace BAA
{



	class Emotion:public BasicObject
	{
	public:

		/************************************************************************/
		/* Default Constructor, name
		/************************************************************************/
		Emotion(const std::string name) :
				BasicObject(name)
		{
		}
	    
		/************************************************************************/
		/* Destructor   Delete basic object as well.                                                                  */
		/************************************************************************/
		~Emotion()
		{

		}

		inline void Initialize( Function * activateFunction, Function * deactivateFunction, float currentValue, float decayRate)
		{
			mActivationFunction = activateFunction;
			mDeactivationFunction = deactivateFunction;
			mValue = currentValue;
			mDecayRate = decayRate;
		}

		inline void Initialize( float currentValue, float decayRate)
		{
			mValue = currentValue;
			mDecayRate = decayRate;
		}

		///************************************************************************/
		///* Returns the name of the emotion                                                                     */
		///************************************************************************/
		//inline const char* GetName() const{return(mName);}


		/************************************************************************/
		/* returns the current value of the emotion                                                                 */
		/************************************************************************/
		inline float GetValue() const{return mValue;}


		/************************************************************************/
		/* Sets the value of the emotion bypassing the activation/deactivation function.
		/* Should be used and is the not the standard update for the emotion. 
		/************************************************************************/
		inline void SetValue(float value){mValue = value;}


		inline void InitializeValue(float value)
		{
			mValue = mActivationFunction->calculate(value);
		}

		/************************************************************************/
		/* Applies an emotional increase that uses the activation function to decide
		/* the final value of the emotion.
		/************************************************************************/
		inline void IncreaseEmotion(float value)
		{
			mValue = mActivationFunction->calculate(mValue + value);
		}

		/************************************************************************/
		/* Applies an emotional decrease that uses the deactivation function to decide
		/* the final value of the emotion. 
		/************************************************************************/
		inline void DecreaseEmotion(float value)
		{
			mValue = mDeactivationFunction->calculate(mValue - value);
		}

		/************************************************************************/
		/* Clears the emotion, sets value and decay rate to zero.                                                                    */
		/************************************************************************/
		inline void Clear(void)
		{
			mValue = 0;
			mDecayRate = 0;

		}


		/************************************************************************/
		/* Every update, the emotion occurs as a function of the deactivate function and decay rate.                                                                     */
		/************************************************************************/
		virtual void Update(float elapsedTime)
		{
			
			mValue = mDeactivationFunction->calculate(mValue - mDecayRate*elapsedTime);

		}



		/************************************************************************/
		/*                                                                      */
		/************************************************************************/
		inline float DecayRate() const { return mDecayRate; }


		inline void DecayRate(float val) { mDecayRate = val; }

		Function* ActivationFunction() const { return mActivationFunction; }
		void ActivationFunction(Function* val) { mActivationFunction = val; }

		Function* DeactivationFunction() const { return mDeactivationFunction; }
		void DeactivationFunction(Function* val) { mDeactivationFunction = val; }

		inline Emotion* Copy()
		{
			Emotion * copy = new Emotion(this->Name());
			copy->Initialize(ActivationFunction(), DeactivationFunction(), mValue, mDecayRate);
			return copy;
		}


	protected:
		float		mValue;
		float		mDecayRate;

		Function*	mActivationFunction;
		Function*	mDeactivationFunction;

	};// end class


	//////////////////////////////////////////////////////////////////////////
	// Emotion Maps
	//////////////////////////////////////////////////////////////////////////

	typedef std::map<const Emotion*, Emotion*, std::less<const Emotion*>>		EmotionEmotionMap;
	typedef std::map<const std::string, Emotion*>			StringEmotionMap;
}
